/**
 * VYPe11 Project
 * VYPe11 language compiler.
 * Authors: Jozef Lang (xlangj01), 
 * 			Zoltan Zemko (xzemko01)
 * 2011
 */

package cz.vutbr.fit.VYPe.team18.VYPe11;

import java.io.*;

import cz.vutbr.fit.VYPe.team18.VYPe11.exception.CodeGenerationException;
import cz.vutbr.fit.VYPe.team18.VYPe11.exception.LexicalException;
import cz.vutbr.fit.VYPe.team18.VYPe11.exception.SematicException;
import cz.vutbr.fit.VYPe.team18.VYPe11.exception.SyntaxException;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.GlobalItemListNode;
import cz.vutbr.fit.VYPe.team18.VYPe11.sematic.TreeWalker;

import cz.vutbr.fit.VYPe.team18.VYPe11.codegeneration.*;
import cz.vutbr.fit.VYPe.team18.VYPe11.codegeneration.MIPS32.*;;

/**
 * Library class.
 */
public final class Utils {
	
	private static final String PROJECT_NAME = "VYPe11"; 
	
	public static int NO_ERROR = 0;
	public static int LEXICAL_ERROR = 1;
	public static int SYNTACTIC_ERROR = 2;
	public static int SEMANTIC_ERROR = 3;
	public static int CODE_GENERATION_ERROR = 4;
	public static int INTERNAL_ERROR = 5;
	
	/**
	 * Prints out message.
	 * @param m message
	 */
	public static void printMessage(String m) {
		if (!m.isEmpty()) 
			System.out.printf("%s: %s\n", Utils.PROJECT_NAME, m);
	}
	
	/**
	 * Prints out message to err.
	 * @param m message
	 */
	public static void printError(String m) {
		if (!m.isEmpty()) 
			System.err.printf("%s: %s\n", Utils.PROJECT_NAME, m);
	}
	
	/**
	 * Prints out help.
	 */
	public static void printHelp() {
		System.out.printf("%s 2011, %s, %s\n", Utils.PROJECT_NAME, "Jozef Lang", "Zoltan Zemko");
		System.out.printf("%s [-h] input [output]\n", Utils.PROJECT_NAME);
		System.out.printf("\n", Utils.PROJECT_NAME);
	}
	
	/**
	 * Compiles input file into and produces output file.
	 * @param input Input file name.
	 * @param output Output file name.
	 * @return Compilation error identificator.
	 */
	public static int compile(String input, String output) {
		File inputFile = new File(input);
		File outputFile = new File(output);
		
		// Check whether input file exists, if not quit 
		if (!inputFile.exists()) {
			//Utils.printError(String.format("file '%s' not found", input));
			return Utils.INTERNAL_ERROR;
		}
		
		try {
	        Scanner s = new Scanner(new FileReader(inputFile));
	        parser p = new parser(s);
	        
	        //  p.debug_parse();
	        GlobalItemListNode root=(GlobalItemListNode)p.parse().value;
	        TreeWalker tw=new TreeWalker();
	        tw.analyze(root);
	        
	        // TAC generation
	        String TACFile =String.format("%s.tac", output);
	        root.generateTACtoFile(TACFile);
	        
	        // ASM Generation
	        InputStream inStream = new FileInputStream(TACFile);
	        OutputStream outStream = new FileOutputStream(outputFile);
	        try {
	        	IASMGenerator mips32 = new MIPS32AssemblerGenerator();
	        	mips32.generateAssembler(inStream, outStream);
	    	} catch (Exception e) {
	    			throw new CodeGenerationException(e.getMessage());
	    	}
	    	finally {
	    		if (inStream != null)
	    			inStream.close();
	    		if (outStream != null)
	    			outStream.close();
	    	}
	        //Utils.printMessage("No errors.");
	    }
		catch(LexicalException lexExc) {
			//Utils.printError(String.format("Lexical error: %s",lexExc.getErrorMessage()));
			return Utils.LEXICAL_ERROR;
		}
		catch(SyntaxException syntExc) {
			//Utils.printError(String.format("Syntactic error: %s", syntExc.getErrorMessage()));
			return Utils.SYNTACTIC_ERROR;
		}
		catch(SematicException semExc)
		{
			//Utils.printError(String.format("Sematic error: %s", semExc.getErrorMessage()));
			return Utils.SEMANTIC_ERROR;
		}
		catch(CodeGenerationException cgExc) {
			//Utils.printError(String.format("Code generation error: %s", cgExc.getErrorMessage()));
			return Utils.CODE_GENERATION_ERROR;
		}
	    catch (Exception exc) {
	    	//Utils.printError(String.format("Internal error: ", exc.getMessage()));
	    	return Utils.INTERNAL_ERROR;
	    }
		
		return Utils.NO_ERROR;
	}	
}
